package game.controlling;
import java.util.TreeMap;
import java.util.Vector;

import org.lwjgl.input.Keyboard;

import tools.Help;
import tools.Log;
import tools.Point;
import tools.ReadFile;
public class LocalController extends Controller {
	private TreeMap<String, String> commandToKeyString;
	private TreeMap<String, String> keyToCommandString;
	public KeyListener keyListener;
	private Point mp;
	public LocalController(KeyListener controller) {
		this.keyListener = controller;
		commandToKeyString = new TreeMap<String, String>();
		keyToCommandString = new TreeMap<String, String>();
		initialize();
		mp = new Point();
	}
	/**
	 * @author toni Returns true when the keyboard/mouse button that has been assigned to the given command string is touched. A button/key is touched during the first frame it has been pressed down, not as long as it is held down.
	 * @param c
	 *            The Command that is checked.
	 * @return
	 */
	@Override
	public boolean touchedGame(String c) {
		assert (commandToKeyString.containsKey(c)) : "Invalid command string: " + c;
		return touched(commandToKeyString.get(c));
	}
	public boolean touched(String c) {
		int key = getKey(c);
		if (key == 0 || key == 1) {
			return keyListener.cButtons.contains(key);
		}
		else {
			return keyListener.cKeys.contains(key);
		}
	}
	/**
	 * @author toni Returns true when the keyboard/mouse button that has been assigned to the given command string is pressed. A button/key is pressed as long as it is held down.
	 * @param c
	 *            The Command that is checked.
	 * @return
	 */
	@Override
	public boolean pressedGame(String c) {
		assert (commandToKeyString.containsKey(c)) : "Invalid command string: " + c;
		return pressed(commandToKeyString.get(c));
	}
	public boolean pressed(String c) {
		int key = getKey(c);
		if (key == 0 || key == 1) {
			return keyListener.buttons.contains(key);
		}
		else {
			return keyListener.keys.contains(key);
		}
	}
	public boolean released(String c) {
		int key = getKey(c);
		if (key == 0 || key == 1) {
			return keyListener.rButtons.contains(key);
		}
		else {
			return keyListener.rKeys.contains(key);
		}
	}
	@Override
	public boolean releasedGame(String c) {
		assert (commandToKeyString.containsKey(c)) : "Invalid command string: " + c;
		return released(commandToKeyString.get(c));
	}
	public String getString(int key) {
		if (key == 0)
			return "mbl";
		if (key == 1)
			return "mbr";
		if (key >= 2 && key <= 11) {
			return String.valueOf("1234567890".charAt(key - 2));
		}
		final int[] characterKeys = new int[]{30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44};
		String lowercase = "abcdefghijklmnopqrstuvwxyz";
		int index = 0;
		for (int k : characterKeys) {
			if (k == key) {
				return String.valueOf(lowercase.charAt(index));
			}
			index++;
		}
		return null;
	}
	public int getKey(String c) {
		// Check mouse buttons
		if ("mbl".equals(c)) {
			return 0;
		}
		if ("mbr".equals(c)) {
			return 1;
		}
		// Check numbers
		String numbers = "1234567890";
		if (numbers.contains(c)) { // String is a number
			int index = numbers.indexOf(c);
			int key = 2 + index;
			return key;
		}
		// Check literals
		final int[] characterKeys = new int[]{30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44};
		String lowercase = "abcdefghijklmnopqrstuvwxyz";
		if (lowercase.contains(c)) {
			return characterKeys[lowercase.indexOf(c)];
		}
		return -1;
	}
	public String getIdentifier(String command) {
		return keyToCommandString.get(command);
	}
	private void initialize() {
		initializeControls();
	}
	private void initializeControls() {
		final String assignmentOperator = "=";
		String controlsFileContent = ReadFile.getContents("config/controls");
		Vector<String> identifiers = new Vector<String>();
		for (String line : controlsFileContent.split(System.getProperty("line.separator"))) {
			line = line.replace(" ", ""); // Delete spaces
			if (line.contains(assignmentOperator)) {
				String[] splitted = line.split(assignmentOperator);
				if (splitted.length != 2) {
					Log.game("Controls config file invalid, skipping line.");
				}
				String key = splitted[0];
				String value = splitted[1];
				commandToKeyString.put(key, value);
				keyToCommandString.put(value, key);
				identifiers.add(key);
			}
		}
		// The Control data class needs to be initialized with all the possible
		// commands ("jump", "walkLeft", ...)
		new ControlData(identifiers);
	}
	@Override
	public Point getMp() {
		return mp;
	}
	public void setMp(Point mp) {
		this.mp = mp;
	}
	public void setKeyListener(KeyListener keyListener) {
		this.keyListener = keyListener;
	}
	@Override
	public void clear() {
		setMp(keyListener.mp);
		keyListener.clear();
	}
}
